﻿//Copyright (C) <2013>  <jonathan cleeve norton> All Rights Reserved 
//Contact jon.norton@fin-plus.co.uk website <http://www.fin-plus.co.uk/>
using System;
using System.Linq;
using System.Collections.Generic;
using System.Reflection;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using FinPlusInterfaces;
using FinPlusAssembler;

namespace FinPlusCompView
{
    public static class PodExtension
    {
        public static string Replace(this IPod pod,string value)
        {
            var beans = (string[][])value.ToJaggedArray(';', ',');

            foreach (var bean in beans)
            {
                if (bean.Count() < 2) 
                    continue;

                if (!bean[1].StartsWith("[") || !bean[1].EndsWith("]"))
                    continue;

                var i = pod.Get(bean[1].TrimStart('[').TrimEnd(']'));

                if (i != null)
                    value = value.Replace(bean[1], i.ToString());
            }

            return value;
        }

        public static IDictionary<DateTime, object> DateSeries(this IDPod pod)
        {
            return pod.GetBeans().Where(x => x.Value.Object.GetType() == typeof(double)).ToDictionary(x => DateTime.Parse(x.Key), x => x.Value.Object);
        }

        public static IPods Get(this IPods pods, Assembly assembly = null)
        {
            var infos = IOC.New<IPods>();

            var order = 0;
            foreach (var pod in pods.Values)
                infos.Add(pod.Get(assembly, infos.NextKey(), order++));

            return infos;
        }

        public static IPod Get(this IPod pod, Assembly assembly, int id = -1, int order = 0)
        {
            var info = IOC.New<IPod>("BeanInfo", id.ToString(), "System", id);
            info["Order"] = order;
            info[PodField.Type.ToString()] = pod[PodField.Type.ToString()];
            info[PodField.Id.ToString()] = pod[PodField.Id.ToString()].ToString();
            info["IsBuilt"] = 0;
            info["IsValid"] = 0;
            info["Pod"] = pod;
            info["Properties"] = IOC.New<IPod>("Properties");
            info["Methods"] = IOC.New<IPod>("Methods");
            info["Invoke"] = pod.Invoke ?? string.Empty;
            info["Exception"] = string.Empty;

            if (pod.Object == null)
                return info;

            Exception e = null;
            IFinPlusComp component = null;

            if (pod.Object is Exception && pod.Object.TryCast<Exception>(null, out e))
            {
                info["Exception"] = e.Message;
                info["IsBuilt"] = -1;
            }
            else if (pod.Object.TryCast<IFinPlusComp>(null, out component))
            {
                info["IsBuilt"] = 1;
                info["IsValid"] = component.IsValid ? 1 : -1;
                info["Properties"] = GetProperties(pod);
                info["Methods"] = GetMethods(pod);
            }
            else
            {
                info["IsBuilt"] = 1;
                info["Properties"] = GetProperties(pod);
                info["Methods"] = GetMethods(pod);
            }

            return info;
        }

        public static IPod GetConst(this IPod pod)
        {
            var p = IOC.New<IPod>(string.Format("{0}.{1}", pod[PodField.Type.ToString()].ToString(), "Constructor"));
            if (pod == null || pod.Type == null) 
                return p;

            foreach (var cons in pod.Type.GetConstructors(BindingFlags.Public | BindingFlags.Instance | BindingFlags.DeclaredOnly))
                if (!(cons.Name.Contains("_")))
                    p[cons.Name] = string.Format("({0})", string.Join(",", cons.GetParameters().Select(i => i.ParameterType.Name).ToArray()));

            return p;
        }

        public static IPod GetProperties(this IPod pod)
        {
            var p = IOC.New<IPod>(string.Format("{0}.{1}", pod[PodField.Type.ToString()].ToString(), "Properties"));
            if (pod == null || pod.Type == null) 
                return p;

            foreach (var prop in pod.Type.GetProperties(BindingFlags.Public | BindingFlags.Instance | BindingFlags.DeclaredOnly))
                p[prop.Name] = " " + prop.PropertyType.Name;

            return p;
        }

        public static IPod GetMethods(this IPod pod)
        {
            var p = IOC.New<IPod>(string.Format("{0}.{1}", pod[PodField.Type.ToString()].ToString(), "Methods"));
            if (pod == null || pod.Type == null) 
                return p;

            foreach (var meth in pod.Type.GetMethods(BindingFlags.Public | BindingFlags.Instance | BindingFlags.DeclaredOnly))
                if (!(meth.Name.Contains("_")))
                    p[meth.Name] = string.Format("({0})", string.Join(",", meth.GetParameters().Select(i => i.ParameterType.Name).ToArray()));

            return p;
        }

        public static void Render(this IPod pod, double height = 2000, double with = 2000)
        {

            var viewbox = new Viewbox();
            viewbox.Child = (FinPlusControl)pod.Object;
            viewbox.Measure(new System.Windows.Size(2000, 2000));
            viewbox.Arrange(new Rect(0, 0, 2000, 2000));
            viewbox.UpdateLayout();
            RenderTargetBitmap render = new RenderTargetBitmap(2000, 2000, 150, 150, PixelFormats.Pbgra32);
            render.Render(viewbox);
        }
    }
}
